#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkProperty.h>

#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkAnimationScene.h>
#include <vtkAnimationCue.h>

class vtkCustomAnimationCue : public vtkAnimationCue
{
protected:
	vtkCustomAnimationCue() : RenWin(nullptr), Sphere(nullptr) {}
	virtual void TickInternal(double currenttime, double deltatime, double clocktime)
	{
		double new_st = currenttime * 180;
		this->Sphere->SetStartTheta(new_st);
		this->RenWin->Render();
	}

public:
	static vtkCustomAnimationCue* New();
	vtkTypeMacro(vtkCustomAnimationCue, vtkAnimationCue);
	vtkRenderWindow* RenWin;
	vtkSphereSource* Sphere;
};
vtkStandardNewMacro(vtkCustomAnimationCue);

int main()
{
	// 新建一个 Source 数据源对象
	vtkSmartPointer<vtkSphereSource> sphere = nullptr;
	sphere = vtkSmartPointer<vtkSphereSource>::New();
	// 设置属性
	sphere->SetPhiResolution(30); // 设置纬度方向上的点数，默认值为 8
	sphere->SetThetaResolution(30); // 设置经度方向上的点数，默认值为 8
	// 新建一个 Mapper 映射器对象
	vtkSmartPointer<vtkPolyDataMapper> sphereMapper = nullptr;
	sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	// 接受 cylinder 的输出，将数据映射为几何元素
	sphereMapper->SetInputConnection(sphere->GetOutputPort());
	// 新建一个 Actor 演示对象
	vtkSmartPointer<vtkActor> sphereActor = nullptr;
	sphereActor = vtkSmartPointer<vtkActor>::New();
	// vtkActor 派生自 vtkProp 类，渲染场景中数据的可视化表达是通过 vtkProp 的子类负责的
	// vtkProp 子类负责确定渲染场景中对象的位置、大小和方向信息
	sphereActor->SetMapper(sphereMapper);
	sphereActor->GetProperty()->SetColor(0.0, 0.0, 1.0);
	// 创建一个 Renderer 渲染器对象，负责管理场景的渲染过程
	vtkSmartPointer<vtkRenderer> renderer = nullptr;
	renderer = vtkSmartPointer<vtkRenderer>::New();
	// 添加 vtkProp 类型的对象到渲染场景中
	renderer->AddActor(sphereActor);
	// 设置渲染场景的背景颜色
	renderer->SetBackground(1.0, 1.0, 1.0); // R、G、B，全 0 为黑色，全 1 为白色
	// 创建一个 Window 窗口对象，负责本地计算机系统中窗口创建和渲染过程管理
	vtkSmartPointer<vtkRenderWindow> window = nullptr;
	window = vtkSmartPointer<vtkRenderWindow>::New();
	window->AddRenderer(renderer);
	window->SetSize(640, 480); // 设置窗口大小
	window->Render();
	window->SetWindowName("Sphere");


	// 新建一个 Interactor 交互器对象，提供平台独立的响应鼠标、键盘和时钟事件的交互机制
	vtkSmartPointer<vtkRenderWindowInteractor> interactor = nullptr;
	interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	// 设置渲染窗口，消息是通过渲染窗口捕获到的，所以必须要给交互器对象设置渲染窗口
	interactor->SetRenderWindow(window);
	// 新建一个交互器样式对象，该样式下，用户通过控制相机对物体作旋转、放大、缩小等操作
	vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = nullptr;
	style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
	// 定义交互器样式，默认的交互样式为 vtkInteractorStyleSwitch
	interactor->SetInteractorStyle(style);


	vtkAnimationScene* scene = vtkAnimationScene::New(); // 创建动画场景
	//scene->SetModeToRealTime(); // 设置实时播放模式
	scene->SetModeToSequence(); // 设置顺序播放模式
	scene->SetFrameRate(30); // 设置帧率，单位时间内渲染的帧数
	scene->SetStartTime(0); // 动画开始时间
	scene->SetEndTime(60); // 动画结束时间

	vtkCustomAnimationCue* cue = vtkCustomAnimationCue::New(); // 创建动画实例
	// 对于类中需要操作的对象进行赋值
	cue->Sphere = sphere;
	cue->RenWin = window;
	cue->SetTimeModeToNormalized(); // 按照场景时间标准化实例的动画时间，0 对应动画场景的开始，1 对应结束
	cue->SetStartTime(.0);
	cue->SetEndTime(1.0);

	scene->AddCue(cue); // 添加动画实例到动画场景中
    interactor->Initialize();
	// scene->SetLoop(1); // 设置循环播放模式
	scene->Play(); // 动画场景开始播放
    // scene->Stop(); // 结束播放
    interactor->Start();

	scene->Delete();
	cue->Delete();

	return EXIT_SUCCESS;
}
